<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <script>
    function Human(sex, name) {
      this.sex = sex
      this.name = name
    }
    Human.prototype.eat = function () {
      console.log(`${this.name}正在进食~`)
    }

    let newPrototype
    
    function Fqm(sex, name, yy) {
      Human.call(this, sex, name)
      this.yy = yy

      // 如果直接把原型赋值放在函数的内部，就会出问题的，为什么呢？
      newPrototype = Fqm.prototype
       // 注意：{} + ...解构实际上是new一个新的对象了，就不会出现Fqm.prototype和Human.prototype是同一份数据了
      //  我并不想改了继承的类，基类也会出问题
      Fqm.prototype = {...Human.prototype}
      // 因为在new在函数执行前，就会创建一个空对象
      // 并且把空对象的__proto__指向构造函数的prototype，也就是fqm.__proto__指向Fqm.prototype
      // 此后才会执行函数
      // 那么如果函数执行时把Fqm.prototype改了，那么fqm.__proto__就不指向Fqm.prototype了

    }

    // 在函数外而且在new前就可以了，因为在函数外，new前，就可以先把Fqm.prototype = {...Human.prototype}
    // 在来new的时候，new会把fqm.__proto__指向Fqm.prototype也就是{...Human.prototype}
    // 所以无非就是先后的问题
    // Fqm.prototype = {...Human.prototype}

    let fqm = new Fqm('男', 'fqm', 'yysjjd')
    console.log(fqm.__proto__ === Fqm.prototype)
    console.log(fqm.__proto__ === newPrototype)
    // 如果在函数外赋值Fqm.prototype = {...Human.prototype}，就可以继承原型上的方法了
    fqm.eat()

  </script>

  <!-- <script>
    function Human(sex, name) {
      this.sex = sex
      this.name = name
    }
    Human.prototype.eat = function () {
      console.log(`${this.name}正在进食~`)
    }

    function Fqm(sex, name, yy) {
      Human.call(this, sex, name)
      this.yy = yy
      Fqm.prototype.__proto__ = Human.prototype
      //  Object.setPrototypeOf(Fqm.prototype, Human.prototype)  // 这两者一样效果

      // 这样看起来似乎是好了
      // 但是又出现了一个问题：Fqm.prototype.__proto__和Human.prototype指向了同一个地址，也就是说
      // 我改变了继承的“类”的prototype.__proto__，而“基类”的prototype也跟着改变了
      Fqm.prototype.__proto__.yysjjd = function() {
        console.log(this.name + ':' + this.yy)
      }
    }

    let fqm = new Fqm('男', 'fqm', 'yysjjd')
    console.log(fqm.__proto__ === Fqm.prototype)
    // 可以继承原型上的方法了
    fqm.eat()
    fqm.yysjjd()
    // 但是会改变被继承的“基类”的数据，不可取
    Human.prototype.yysjjd()
  </script> -->

  <!-- <script>
    function Human(sex, name) {
      this.sex = sex
      this.name = name
    }
    Human.prototype.eat = function () {
      console.log(`${this.name}正在进食~`)
    }

    function Fqm(sex, name, yy) {
      Human.call(this, sex, name)
      this.yy = yy
      // 注意：{} + ...解构实际上是new一个新的对象了
      Fqm.prototype.__proto__ = {...Human.prototype}

      Fqm.prototype.__proto__.yysjjd = function() {
        console.log(this.name + ':' + this.yy)
      }

      // 但是实际上还是有不好的地方
      // 因为 __proto__或者Object.setPrototypeOf()都会拖性能，所以，不要用__proto__，看第一个方案就是最好的
    }



    let fqm = new Fqm('男', 'fqm', 'yysjjd')
    console.log(fqm.__proto__ === Fqm.prototype)
    // 可以继承原型上的方法了
    fqm.eat()
    fqm.yysjjd()
    // Uncaught TypeError: Human.prototype.yysjjd is not a function  好了
    Human.prototype.yysjjd()
  </script> -->
  



</body>

</html>